/**
 * 公司的域名倒过来写.项目名.模块名.子包
 */
package com.sys.common.util;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

/**
 * ~标准的JDBC ~单例模式:啥是单例模式;在一个JVM中,只有一个对象 让构造方法私有 提供一个属性;类型是自己,new一个对象
 * 提供一个方法返回值是自己,修饰符是public static
 * 
 * ~封装JDBC 将加载驱动只执行一次 第二步放到一个方法中 将经常修改的内容放到配置文件中;资源文件,ResourceBundle
 * 
 * @author 陈岩
 */
public class DbUtil
{
	/**
	 * 为了属性的安全:设置值和获取值(set/get)
	 */
	private static DbUtil INSTANCE = new DbUtil();

	/* 变量 */
	private String driver = ConstatFinalUtil.SYS_BUNDLE.getString("jdbc.driver");
	/*
	 * jdbc的url; http://www.cnblogs.com/iamfy/archive/2012/07/11/2586869.html
	 * 参数是:url; jdbc:mysql://localhost:3306/userscenter_20180108?user=&password=
	 */
	private String url = ConstatFinalUtil.SYS_BUNDLE.getString("jdbc.url");
	private String user = ConstatFinalUtil.SYS_BUNDLE.getString("jdbc.user");
	private String password = ConstatFinalUtil.SYS_BUNDLE.getString("jdbc.password");

	/**
	 * 私有的构造方法
	 */
	private DbUtil()
	{
		/* 单例模式,此代码只执行一次 */
		try
		{
			/* 加载驱动 */
			Class.forName(driver);
		} catch (ClassNotFoundException e)
		{
			System.out.println("==加载驱动失败==");
			e.printStackTrace();
		}
	}

	/**
	 * static:构造方法私有了,外面的类不能new了,如果此方法不被static修饰,那么getInstance,是必须得new吧;只能被static修饰
	 * 
	 * @return
	 */
	public static DbUtil getInstance()
	{
		return INSTANCE;
	}

	/**
	 * 获取一个链接
	 * 
	 * @return
	 */
	public Connection getConnection()
	{
		/* 获取链接 */
		Connection connection = null;
		try
		{
			connection = DriverManager.getConnection(url, user, password);
		} catch (SQLException e)
		{
			System.out.println("==获取链接失败==");
			e.printStackTrace();
		}
		return connection;
	}

	/**
	 * 关闭链接,关闭语句,关闭rs
	 * 
	 * @param connection jdbc的链接
	 * @param st         sql语句对象
	 * @param rs         查询的结果集
	 */
	public void closeAll(Connection connection, Statement st, ResultSet rs)
	{
		try
		{
			if (rs != null)
			{
				rs.close();
				rs = null;
			}
		} catch (SQLException e)
		{
			e.printStackTrace();
		}

		try
		{
			if (st != null)
			{
				st.close();
				st = null;
			}
		} catch (SQLException e)
		{
			e.printStackTrace();
		}

		try
		{
			if (connection != null)
			{
				connection.close();
				connection = null;
			}
		} catch (SQLException e)
		{
			e.printStackTrace();
		}
	}

	public static void main(String[] args)
	{
		// stardandJDBC();
		encapsulationJDBC();

		/* 测试单例模式 */
		for (int i = 0; i < 10; i++)
		{
			/* 不能new对象,要使用getInstance方法 */
			System.out.println(DbUtil.getInstance());
		}
	}

	/**
	 * 封装后的JDBC
	 */
	public static void encapsulationJDBC()
	{
		System.out.println("==封装后的JDBC==");
		String sql = "select * from a_role ; ";

		PreparedStatement ps = null;
		ResultSet rs = null;

		/* 先创建对象,不能new */
		DbUtil dbUtil = DbUtil.getInstance();
		/* 获取链接 */
		Connection connection = dbUtil.getConnection();
		try
		{
			ps = connection.prepareStatement(sql);
			rs = ps.executeQuery();
			/*
			 * 到底是循环还是选择 如果查询的结果是多条,就用判断 如果是单条:就用选择
			 * 
			 * rs == 班长== 迭代器==enumeration(枚举)
			 */
			while (rs.next())
			{
				/*
				 * 参数为整数:指的是sql语句执行以后;列的顺序 参数为字符串时:指的是sql语句执行以后列的别名;
				 */
				int id = rs.getInt(1);
				String name = rs.getString("name");
				System.out.println("id:" + id + ";name" + name);
			}
		} catch (SQLException e)
		{
			e.printStackTrace();
		} finally
		{
			dbUtil.closeAll(connection, ps, rs);
		}
	}

	/**
	 * 标准的JDBC代码 查询角色表中所有记录
	 */
	private static void stardandJDBC()
	{
		/*
		 * Jdbc:四步走: 加载驱动 获取链接 操作数据库 关闭链接
		 * 
		 * 查询角色表中所有的记录
		 */
		String driver = "com.mysql.jdbc.Driver";
		/*
		 * jdbc的url; http://www.cnblogs.com/iamfy/archive/2012/07/11/2586869.html
		 * 参数是:url; jdbc:mysql://localhost:3306/userscenter_20180108?user=&password=
		 */
		String url = "jdbc:mysql://localhost:3306/userscenter_20180108?useSSL=true";
		String user = "root";
		String password = "123456";
		/* 写上sql语句 */
		String sql = "select * from a_role ; ";

		/* 为对象赋初始值 */
		Connection connection = null;
		PreparedStatement ps = null;
		ResultSet rs = null;
		try
		{
			/* 加载驱动 */
			Class.forName(driver);
			/* 获取链接 */
			connection = DriverManager.getConnection(url, user, password);
			/*
			 * 操作数据库 创建一个SQL语句,将SQL语句发送到数据库中 Statement:木有预先加载; String name = "aa" ; String
			 * pass = "' or 1 = 1 or name = '232323232323" ;//SQL注入 select * from users
			 * where name = '"+ name +"' and password = '" + name + "' ;
			 * preparedStatement:预先加载 ?:占位符 SQL注入
			 */
			ps = connection.prepareStatement(sql);
			rs = ps.executeQuery();
			/*
			 * 到底是循环还是选择 如果查询的结果是多条,就用判断 如果是单条:就用选择
			 * 
			 * rs == 班长== 迭代器==enumeration(枚举)
			 */
			while (rs.next())
			{
				/*
				 * 参数为整数:指的是sql语句执行以后;列的顺序 参数为字符串时:指的是sql语句执行以后列的别名;
				 */
				int id = rs.getInt(1);
				String name = rs.getString("name");
				System.out.println("id:" + id + ";name" + name);
			}
		} catch (ClassNotFoundException e)
		{
			System.out.println("==加载驱动失败==");
			e.printStackTrace();
		} catch (SQLException e)
		{
			System.out.println("==获取链接失败==");
			e.printStackTrace();
		} finally
		{
			try
			{
				if (rs != null)
				{
					rs.close();
					rs = null;
				}
			} catch (SQLException e)
			{
				e.printStackTrace();
			}

			try
			{
				if (ps != null)
				{
					ps.close();
					ps = null;
				}
			} catch (SQLException e)
			{
				e.printStackTrace();
			}

			try
			{
				if (connection != null)
				{
					connection.close();
					connection = null;
				}
			} catch (SQLException e)
			{
				e.printStackTrace();
			}
		}
	}
}
